﻿using System;
using System.Data;
using System.Configuration;
using System.Reflection;
using System.Collections.Generic;
using System.Xml;
using JWFW.Encrypt;
using System.IO;

namespace JWFW.SFL
{
    /// <summary>
    /// 自定义配置类；
    /// 使用实例访问；
    /// 优先级顺序：外部的配置 > 程序集内部配置；
    /// 取值顺序：
    /// 外属性 > 外标签 > 外强属性 > 外强标签 >内属性 > 内标签 
    /// > 内强属性 > 内强标签  > 外默属性 > 外默标签 > 内默属性 > 内默标签；
    /// id只能为属性；
    /// </summary>
    public class ConfigOP
    {
        public ConfigOP()
        {
        }
        /// <summary>
        /// 缓存从文件中读取的xmldocument对象
        /// </summary>
        protected static Dictionary<string, XmlDocument> s_cacheXML = new Dictionary<string, XmlDocument>();
        protected static Base64 s_b64 = new Base64();
        /// <summary>
        /// 清除缓存的XmlDocument，便于不重启动进程就可以更新配置文件
        /// </summary>
        public static void ClearCache()
        {
            s_cacheXML.Clear();
        }


        private string m_fileDirectory = "";
        private string m_fileName = "config.cfg";
        private Assembly m_containerAssembly = Assembly.GetEntryAssembly();
        private string m_namespace = null;
        private string m_nodePath = "map//msg";
        private string m_idAttribute = "id";
        private string m_default = "default";
        private string m_strongDefault = "strongDefault";
        private bool m_encrypt = false;



        /// <summary>
        /// 外部配置文件的路径
        /// </summary>
        public string FileDirectory
        {
            get { return m_fileDirectory; }
            set { m_fileDirectory = value; }
        }
        /// <summary>
        /// 配置文件名
        /// </summary>
        public string FileName
        {
            get { return m_fileName; }
            set { m_fileName = value; }
        }
        /// <summary>
        /// 包含配置文件的程序集
        /// </summary>
        public Assembly ContainerAssembly
        {
            get { return m_containerAssembly; }
            set { m_containerAssembly = value; }
        }
        /// <summary>
        /// 配置文件的名称空间
        /// </summary>
        public string Namespace
        {
            get
            {
                if (m_namespace == null)
                {
                    m_namespace = "";
                    if (ContainerAssembly != null)
                    {
                        m_namespace = ContainerAssembly.GetName().Name;
                    }
                    return m_namespace;
                }
                return m_namespace;
            }
            set { m_namespace = value; }
        }
        /// <summary>
        /// 节点路径
        /// </summary>
        public string NodePath
        {
            get { return m_nodePath; }
            set { m_nodePath = value; }
        }
        /// <summary>
        /// ID属性/标签
        /// </summary>
        public string IdAttribute
        {
            get { return m_idAttribute; }
            set { m_idAttribute = value; }
        }
        /// <summary>
        /// 默认值使用的属性/标签
        /// </summary>
        public string Default
        {
            get { return m_default; }
            set { m_default = value; }
        }
        /// <summary>
        /// 强制默认值使用的属性/标签
        /// </summary>
        public string StrongDefault
        {
            get { return m_strongDefault; }
            set { m_strongDefault = value; }
        }
        /// <summary>
        /// 是否加密外部资源
        /// </summary>
        public bool Encrypt
        {
            get { return m_encrypt; }
            set { m_encrypt = value; }
        }

        /// <summary>
        /// 获取外部的XML
        /// </summary>
        /// <returns></returns>
        protected XmlDocument GetOuterXML()
        {
            string fileName = System.IO.Path.Combine(m_fileDirectory, m_fileName);
            if (!s_cacheXML.ContainsKey(fileName))
            {
                XmlDocument doc = new XmlDocument();
                try
                {
                    if (!m_encrypt)
                    {
                        doc.Load(fileName);
                    }
                    else
                    {
                        string origin = System.IO.File.ReadAllText(fileName);
                        if (MD5.ValidateValue(origin))
                        {
                            doc.LoadXml(s_b64.Decode(MD5.RemoveMD5Profix(origin)));
                        }
                        
                    }
                }
                catch { }
                s_cacheXML.Add(fileName, doc);
            }
            return s_cacheXML[fileName];
        }
        /// <summary>
        /// 获取嵌入的XML
        /// </summary>
        /// <returns></returns>
        protected XmlDocument GetInnerXML()
        {
            string fileName = this.Namespace + "." + m_fileName;
            if (!s_cacheXML.ContainsKey(fileName))
            {
                XmlDocument doc = new XmlDocument();
                try
                {
                    Stream st = m_containerAssembly.GetManifestResourceStream(fileName);
                    doc.Load(st);
                    st.Close();
                }
                catch { }
                s_cacheXML.Add(fileName, doc);
            }
            return s_cacheXML[fileName];
        }

        /// <summary>
        /// 从XML中获取字符串
        /// </summary>
        /// <param name="id">id</param>
        /// <param name="name">name</param>
        /// <param name="msg">获取的字符串</param>
        /// <param name="doc">xml</param>
        /// <param name="args">字符串中的参数</param>
        /// <returns></returns>
        protected bool GetStringFromXML(string id, string name, out string msg, XmlDocument doc, params string[] args)
        {
            bool res = false;
            string xpath = string.Format("{0}[@{1}=\"{2}\"]", m_nodePath, m_idAttribute, id);
            XmlNode nd = doc.SelectSingleNode(xpath);
            if (this.GetStringFromNode(nd, name, out msg, args))
            {
                res = true;
            }
            else if (this.GetStringFromNode(nd, m_strongDefault, out msg, args))
            {
                res = true;
            }
            return res;
        }
        /// <summary>
        /// 从XML中获取默认的字符串【级别最低】
        /// </summary>
        /// <param name="id">id</param>
        /// <param name="msg">获取的字符串</param>
        /// <param name="doc">xml</param>
        /// <param name="args">字符串中的参数</param>
        /// <returns></returns>
        protected bool GetStringFromXMLDefault(string id, out string msg, XmlDocument doc, params string[] args)
        {
            string xpath = string.Format("{0}[@{1}=\"{2}\"]", m_nodePath, m_idAttribute, id);
            XmlNode nd = doc.SelectSingleNode(xpath);
            return GetStringFromNode(nd, m_default, out msg, args);
        }
        /// <summary>
        /// 从XML节点中获取字符串，优先获取属性，其次为子标签
        /// </summary>
        /// <param name="nd">xml节点</param>
        /// <param name="name">name</param>
        /// <param name="msg">获取的字符串</param>
        /// <param name="args">字符串中的参数</param>
        /// <returns></returns>
        protected bool GetStringFromNode(XmlNode nd, string name, out string msg, params string[] args)
        {
            bool res = false;
            msg = "";
            if (nd != null)
            {
                if (nd.Attributes[name] != null)
                {
                    msg = string.Format(nd.Attributes[name].Value, args);
                    res = true;
                }
                else
                {
                    XmlNode sub = nd.SelectSingleNode(name);
                    if (sub != null)
                    {
                        msg = string.Format(sub.InnerText.Trim(), args);
                        res = true;
                    }
                }
            }
            return res;
        }

        /// <summary>
        /// 获取配置文件中指定的字符串
        /// </summary>
        /// <param name="id">id</param>
        /// <param name="name">name</param>
        /// <param name="args">字符串中的参数</param>
        /// <returns></returns>
        public string GetString(string id, string name, params string[] args)
        {
            string res = "";
            try
            {
                if (this.GetStringFromXML(id, name, out res, this.GetOuterXML(), args))
                {
                    return res;
                }
                if (this.GetStringFromXML(id, name, out res, this.GetInnerXML(), args))
                {
                    return res;
                }
                if (this.GetStringFromXMLDefault(id, out res, this.GetOuterXML(), args))
                {
                    return res;
                }
                if (this.GetStringFromXMLDefault(id, out res, this.GetInnerXML(), args))
                {
                    return res;
                }
                res = string.Format("{0}[{1}]", id, name);
            }
            catch { res = string.Format("{0}[{1}]", id, name); }
            return res;
        }
    }
}
